﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Windows.UI.Xaml.Controls;

namespace G.Net.Oauth
{
    public class Oauth2Valid
    {
        /// <summary>
        /// 刷新AccessToken
        /// </summary>
        /// <returns></returns>
        public async static Task RefreshToken()
        {
            OAuth2AccessToken.Load();
            if (OAuth2AccessToken.CurrentToken == null)
            {
                throw new Exception("无法获取OAuth2AccessToken，请重新登陆");
            }
            string refreshTokenUrl = string.Format("{0}?client_id={1}&client_secret={2}&grant_type=refresh_token&refresh_token={3}&scope=read,write", Oauth2Config.Token_Authorize_Url, Oauth2Config.ClientID, Oauth2Config.ClientSecret, OAuth2AccessToken.CurrentToken.RefreshToken);
            HttpPost get = new HttpPost(refreshTokenUrl);
            var result = await get.RequestAsync();
            if (result.Exception == null)
            {
                OAuth2AccessToken token = G.Utils.SerializerHelp.JsonDeserialize<OAuth2AccessToken>(result.Result);
                token.Save(result.Result);
            }
            else
                throw new Exception("获取token失败");
        }


        static System.Threading.Tasks.TaskCompletionSource<string> task;
        /// <summary>
        /// 验证oauth2.0权限，获取AccessToken
        /// </summary>
        /// <returns></returns>
        public async static Task<OAuth2AccessToken> Valid()
        {
            var t = OAuth2AccessToken.Load();
            if (t != null)
                return t;
            string authorize_url = string.Format("{0}?client_id={1}&response_type={2}&redirect_uri={3}&scope=read,write", Oauth2Config.Request_Authorize_Url, Oauth2Config.ClientID, Oauth2Config.Authorize_ResponseType, Oauth2Config.RedirectUri);
            G.Controls.ChildWindow oc = new G.Controls.ChildWindow();
            WebView web = new WebView();
            oc.Content = web;
            web.Navigate(new Uri(authorize_url));
            web.LoadCompleted += web_LoadCompleted;
            oc.IsOpen = true;
            task = new TaskCompletionSource<string>();
            string code = await task.Task;
            oc.IsOpen = false;
            task = null;
            HttpGet get = new HttpGet(Oauth2Config.Token_Authorize_Url);
            get.Params.Add("client_id", Oauth2Config.ClientID);
            get.Params.Add("client_secret", Oauth2Config.ClientSecret);
            get.Params.Add("grant_type", "authorization_code");
            get.Params.Add("code", code);
            get.Params.Add("redirect_uri", Oauth2Config.RedirectUri);
            var result = await get.RequestAsync();
            if (result.Exception == null)
            {
                OAuth2AccessToken token = G.Utils.SerializerHelp.JsonDeserialize<OAuth2AccessToken>(result.Result);
                token.Save(result.Result);
                return token;
            }
            throw new Exception("获取token失败");
        }

        static void web_LoadCompleted(object sender, Windows.UI.Xaml.Navigation.NavigationEventArgs e)
        {
            if (e.Uri.OriginalString.StartsWith(Oauth2Config.RedirectUri))
            {
                string code = e.Uri.Query;
                string pa = "code=(.+?)$";
                var match = Regex.Match(code, pa, RegexOptions.IgnoreCase);
                if (!match.Success)
                    throw new Exception("检索code失败！");
                code = match.Groups[1].Value;
                task.SetResult(code);
            }
        }

    }

    [DataContract]
    public class OAuth2AccessToken
    {
        internal static OAuth2AccessToken Load()
        {
            var settings = Windows.Storage.ApplicationData.Current.LocalSettings;
            if (settings.Values.ContainsKey("OAuth2AccessToken"))
            {
                var token = G.Utils.SerializerHelp.JsonDeserialize<OAuth2AccessToken>(settings.Values["OAuth2AccessToken"] as string);
                CurrentToken = token;
                return token;
            }
            return null;
        }
        public static void Clrear()
        {
            var settings = Windows.Storage.ApplicationData.Current.LocalSettings;
            if (settings.Values.ContainsKey("OAuth2AccessToken"))
            {
                settings.Values.Remove("OAuth2AccessToken");
            }
        }
        public static OAuth2AccessToken CurrentToken { get; internal set; }
        public OAuth2AccessToken()
        {
            CurrentToken = this;
        }

        [DataMember(Name = "access_token")]
        public string AccessToken { get; set; }

        [DataMember(Name = "expires_in")]
        public string ExpiresIn { get; set; }

        [DataMember(Name = "refresh_token")]
        public string RefreshToken { get; set; }

        [DataMember(Name = "token_type")]
        public string TokenType { get; set; }

        [DataMember(Name = "uid")]
        public string Uid { get; set; }

        [DataMember(Name = "scope")]
        public string Scope { get; set; }

        internal void Save(string jsonStr)
        {
            Windows.Storage.ApplicationData.Current.LocalSettings.Values["OAuth2AccessToken"] = jsonStr;
            CurrentToken = this;
        }
    }
}
